package longAddrDemo;

import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.BrokenBarrierException;
import java.util.concurrent.CyclicBarrier;
import java.util.concurrent.ThreadLocalRandom;
import java.util.concurrent.atomic.LongAccumulator;
import java.util.concurrent.atomic.LongAdder;
import java.util.function.LongBinaryOperator;

public class LongAccumulatorTest {
    /**
     * 没有incrementAndGet decrementAndGet这种方法，只有单独的increment,longVlaue这种方法
     * 如果组合使用则需要自己做同步控制，否则无法保证原子性
     * LongAddr本质上是一种空间换时间的策略，累加器家族还有一下三种
     * java.util.concurrent.atomic.DoubleAddr
     * java.util.concurrent.atomic.LongAccumulator
     * java.util.concurrent.atomic.DoubleAccumulator
     * LongAdder是LongAccumulator的特例，DoubleAdder是DoubleAccumulator的特例
     * Accumulator的特点是可以设置初始值，自定义累加算法
     */
    public static void main(String[] args) throws InterruptedException {
        long start = System.currentTimeMillis();
        LongBinaryOperator lbn = new LongBinaryOperator() {
            @Override
            public long applyAsLong(long left, long right) {
                return left + right*2 + ThreadLocalRandom.current().nextInt(10);
            }
        };
        LongAccumulator la = new LongAccumulator(lbn, 1);
        System.out.println("la.longValue() = " + la.longValue());

        List<Thread> list = new ArrayList<>();
        for (int i = 0; i < 100; i++) {
            Thread t = new Thread(() -> {
                la.accumulate(2);
            });
            list.add(t);
        }
        for (Thread thread : list) {
            thread.start();
        }
        for (Thread thread : list) {
            thread.join();
        }
        long end = System.currentTimeMillis();
        System.out.println("end - start = " + (end - start) + " " + la.longValue());
    }
}
